package com.codeworker.app.ui.bill;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.recyclerview.widget.RecyclerView;

import com.codeworker.app.R;
import com.codeworker.app.data.common.enums.BillTypeColorEnum;
import com.codeworker.app.data.common.enums.BillTypeEnum;
import com.codeworker.app.data.common.enums.PayTypeEnum;
import com.codeworker.app.data.entity.Bill;
import com.codeworker.app.data.entity.MonthlyRecord;
import com.codeworker.app.data.entity.vo.BillTypeRank;
import com.codeworker.app.data.repository.BillRepository;
import com.codeworker.app.data.repository.PropertyRepository;
import com.codeworker.app.data.entity.vo.BillProportion;
import com.codeworker.app.databinding.ActivityBillInfoBinding;
import com.codeworker.app.ui.wrapper.MyBaseActivity;
import com.codeworker.app.utils.FormatUtil;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

import lecho.lib.hellocharts.model.PieChartData;
import lecho.lib.hellocharts.model.SliceValue;
import lecho.lib.hellocharts.view.PieChartView;

public class MonthlyBillInfoActivity extends MyBaseActivity {

    private LinearLayout llProportion;
    private LinearLayout llRank;
    private TextView tvToolbarTurn;
    private TextView tvPayMoney;
    private TextView tvPayTimes;
    private RecyclerView rvProportion;
    private PieChartView pcvProportion;
    private RecyclerView rvRank;
    private TextView tvInfoTitle;
    private TextView tvProportionTitle;
    private TextView tvRankTitle;
    private TextView tvPayTypeTitle;
    private TextView tvPayTimesTitle;
    private TextView tvStatisticsByType;
    private TextView tvStatisticsByProperty;
    private TextView tvMore;
    private MonthlyRecord monthlyRecord;
    private BillMonthlyRankListAdapter billMonthlyRankListAdapter;
    private BillMonthlyTypeListAdapter billMonthlyTypeListAdapter;
    private List<Bill> monthlyBill;
    private List<BillTypeRank> monthlyBillRank;
    private List<SliceValue> sliceValues;
    private boolean inExpendAction;
    private boolean inTypeStatics;
    public static final String MONTHLY_RECORDS_MONTH = "monthlyRecordsMonth";
    public static final String MONTHLY_RECORDS_YEAR = "monthlyRecordsYear";
    public static final String MONTHLY_RECORDS_PAY_TYPE = "monthlyRecordsPayType";
    private PropertyRepository propertyRepository;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityBillInfoBinding binding = ActivityBillInfoBinding.inflate(getLayoutInflater());
        View root = binding.getRoot();
        setContentView(root);
        setToolbar(this);
        initBaseData(root);
        initOtherData(inExpendAction, inTypeStatics);

        tvToolbarTurn.setOnClickListener(view -> {
            inExpendAction = !inExpendAction;
            initOtherData(inExpendAction, inTypeStatics);
        });
        tvStatisticsByType.setOnClickListener(view -> {
            inTypeStatics = true;
            tvStatisticsByProperty.setTextColor(Color.parseColor("#E8F0F2"));
            tvStatisticsByType.setTextColor(Color.GRAY);
            initOtherData(inExpendAction, inTypeStatics);
        });
        tvStatisticsByProperty.setOnClickListener(view -> {
            inTypeStatics = false;
            tvStatisticsByProperty.setTextColor(Color.GRAY);
            tvStatisticsByType.setTextColor(Color.parseColor("#E8F0F2"));
            initOtherData(inExpendAction, inTypeStatics);
        });
        tvMore.setOnClickListener(view -> {
            Intent intent = new Intent(this, BillMonthlyRankInfoActivity.class);
            Bundle bundle = new Bundle();
            bundle.putInt(MONTHLY_RECORDS_MONTH, monthlyRecord.getMonth());
            bundle.putInt(MONTHLY_RECORDS_YEAR, monthlyRecord.getYear());
            bundle.putInt(MONTHLY_RECORDS_PAY_TYPE,
                    inExpendAction ? PayTypeEnum.EXPEND.getPayTypeInDB() : PayTypeEnum.INCOME.getPayTypeInDB());
            intent.putExtras(bundle);
            startActivity(intent);
        });
    }

    @SuppressLint("SetTextI18n")
    private void initOtherData(boolean inExpendAction, boolean inTypeStatics) {
        int payType;
        int month = monthlyRecord.getMonth();
        if (inExpendAction) {
            tvPayMoney.setText(FormatUtil.format(monthlyRecord.getExpend() * 1.0 / 100));
            tvInfoTitle.setText(month + "月支出账单");
            tvProportionTitle.setText(R.string.text_monthly_bill_expend_proportion_title);
            tvRankTitle.setText(R.string.text_monthly_bill_expend_rank);
            tvPayTypeTitle.setText(R.string.text_monthly_bill_expend);
            tvPayTimesTitle.setText(R.string.text_monthly_bill_expend_times);
            payType = PayTypeEnum.EXPEND.getPayTypeInDB();
        } else {
            tvPayMoney.setText(FormatUtil.format(monthlyRecord.getIncome() * 1.0 / 100));
            tvInfoTitle.setText(month + "月收入账单");
            tvProportionTitle.setText(R.string.text_monthly_bill_income_proportion_title);
            tvRankTitle.setText(R.string.text_monthly_bill_income_rank);
            tvPayTypeTitle.setText(R.string.text_monthly_bill_income);
            tvPayTimesTitle.setText(R.string.text_monthly_bill_income_times);
            payType = PayTypeEnum.INCOME.getPayTypeInDB();
        }
        long times = monthlyBill.stream()
                .filter(bill -> payType == bill.getPayType())
                .count();
        tvPayTimes.setText(String.valueOf(times));
        if (times == 0) {
            llRank.setVisibility(View.GONE);
            llProportion.setVisibility(View.GONE);
            return;
        } else {
            llRank.setVisibility(View.VISIBLE);
            llProportion.setVisibility(View.VISIBLE);
        }
        if (inTypeStatics) {
            setMonthlyRank(monthlyBill, inExpendAction, Bill::getType, billProportion ->
                    BillTypeEnum.getBillDesc(payType, billProportion.getBillType()));
        } else {
            setMonthlyRank(monthlyBill, inExpendAction, Bill::getPropertyId, billProportion ->
                    propertyRepository.getPropertyById(billProportion.getBillType()).getName());
        }
        setPieChartData();
        initPieChart();
        billMonthlyTypeListAdapter.submitList(monthlyBillRank);
        rvProportion.setAdapter(billMonthlyTypeListAdapter);
        List<Bill> monthlyBillTop3 = monthlyBill.stream()
                .filter(bill -> payType == bill.getPayType())
                .sorted(Comparator.comparing(Bill::getValue).reversed())
                .limit(3)
                .collect(Collectors.toList());
        billMonthlyRankListAdapter.submitList(monthlyBillTop3);
        rvRank.setAdapter(billMonthlyRankListAdapter);
    }

    @SuppressLint("SetTextI18n")
    private void initBaseData(View root) {
        llProportion = root.findViewById(R.id.ll_proportion);
        llRank = root.findViewById(R.id.ll_rank);
        tvToolbarTurn = root.findViewById(R.id.tv_toolbar_handle);
        TextView tvToolbarTitle = root.findViewById(R.id.tv_toolbar_title);
        tvInfoTitle = root.findViewById(R.id.tv_bill_info_title);
        tvPayTypeTitle = root.findViewById(R.id.tv_bill_info_title1);
        tvPayTimesTitle = root.findViewById(R.id.tv_bill_info_title2);
        tvPayMoney = root.findViewById(R.id.tv_bill_info1);
        tvPayTimes = root.findViewById(R.id.tv_bill_info2);
        tvProportionTitle = root.findViewById(R.id.tv_monthly_bill_proportion_title);
        pcvProportion = root.findViewById(R.id.pcv_monthly_bill_proportion);
        rvProportion = root.findViewById(R.id.rv_monthly_bill_proportion);
        tvRankTitle = root.findViewById(R.id.tv_monthly_bill_rank_title);
        tvStatisticsByType = root.findViewById(R.id.tv_statistics_by_type);
        tvStatisticsByProperty = root.findViewById(R.id.tv_statistics_by_property);
        tvMore = root.findViewById(R.id.tv_monthly_bill_more_title);
        rvRank = root.findViewById(R.id.rv_monthly_bill_rank);

        monthlyRecord = (MonthlyRecord) getIntent().getExtras().getSerializable(BillMonthlyListAdapter.ITEM_DATA);
        BillRepository billRepository = new BillRepository(getApplication());
        int month = monthlyRecord.getMonth();
        int year = monthlyRecord.getYear();
        tvToolbarTurn.setVisibility(View.VISIBLE);
        tvToolbarTitle.setText(year + "年" + month + "月账单");
        monthlyBill = billRepository.getMonthlyBill(month, year);
        rvProportion.setOverScrollMode(View.OVER_SCROLL_NEVER);
        rvRank.setOverScrollMode(View.OVER_SCROLL_NEVER);
        billMonthlyTypeListAdapter = new BillMonthlyTypeListAdapter(new BillMonthlyTypeListAdapter.ItemDiff());
        billMonthlyRankListAdapter = new BillMonthlyRankListAdapter(new BillMonthlyRankListAdapter.ItemDiff());
        inExpendAction = getIntent().getBooleanExtra("PAY_TYPE_EXPEND", false);
        inTypeStatics = true;
        propertyRepository = new PropertyRepository(this.getApplication());
    }

    private void setMonthlyRank(List<Bill> monthlyBill, boolean inExpendAction, Function<Bill, Integer> typeId,
                                Function<BillProportion, String> typeName) {
        int payType = inExpendAction ? PayTypeEnum.EXPEND.getPayTypeInDB() : PayTypeEnum.INCOME.getPayTypeInDB();
        List<BillProportion> billProportions = new ArrayList<>(monthlyBill.stream()
                .filter(data -> data.getPayType() == payType)
                .map(data -> new BillProportion(typeId.apply(data), data.getValue(), 1))
                .collect(Collectors.toMap(BillProportion::getBillType, a -> a, (o1, o2) -> {
                    o1.setTimes(o1.getTimes() + o2.getTimes());
                    o1.setTotal(o1.getTotal() + o2.getTotal());
                    return o1;
                })).values())
                .stream().sorted(Comparator.comparing(BillProportion::getTotal, Comparator.reverseOrder()))
                .collect(Collectors.toList());
        if (billProportions.isEmpty()) {
            monthlyBillRank = null;
            return;
        }

        BillProportion totalBillProportion = billProportions.stream()
                .reduce((o1, o2) -> new BillProportion(
                        payType, o1.getTotal() + o2.getTotal(), o1.getTimes() + o2.getTimes()))
                .orElse(new BillProportion(0, 0, 0));

        monthlyBillRank = billProportions.stream().limit(20).map(data -> new BillTypeRank(
                BillTypeColorEnum.values()[billProportions.indexOf(data)].getColor(),
                typeName.apply(data),
                data.getTotal() * 1.0 / totalBillProportion.getTotal(),
                data.getTotal(),
                data.getTimes()
        )).collect(Collectors.toList());
    }

    //②获取数据
    private void setPieChartData() {
        if (monthlyBillRank == null) {
            sliceValues.clear();
            return;
        }
        sliceValues = new ArrayList<>();
        for (int i = 0, len = monthlyBillRank.size(); i < len; ++i) {
            BillTypeRank temp = monthlyBillRank.get(i);
            SliceValue sliceValue = new SliceValue(Float.parseFloat(temp.getProportion()),
                    Color.parseColor(temp.getBillTypeColor()));//这里的颜色是一个工具类,随机选择颜色的
            sliceValues.add(sliceValue);
        }
    }

    //③定义一些参数
    private void initPieChart() {
        PieChartData pieChartData = new PieChartData();
        pieChartData.setHasLabels(false);//显示表情
        pieChartData.setHasLabelsOnlyForSelected(true);//点击显示占的百分比
        pieChartData.setHasLabelsOutside(false);//占的百分比是否显示在饼图外面
        pieChartData.setHasCenterCircle(true);//是否是环形显示
        pieChartData.setValues(sliceValues);//填充数据
        pieChartData.setCenterCircleColor(Color.WHITE);//设置环形中间的颜色
        pieChartData.setCenterCircleScale(0.6f);//设置环形的大小级别
        pcvProportion.setPieChartData(pieChartData);
        pcvProportion.setValueSelectionEnabled(false);//选择饼图某一块变大
        pcvProportion.setAlpha(0.9f);//设置透明度
        pcvProportion.setCircleFillRatio(1f);//设置饼图大小
    }

}
